﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Timers;
using System.Net;
using System.Drawing;
using System.Threading;
using System.Windows.Threading;
using AsyncCamera.Camera.Structure;
using Incendios0_1.Camera.wpfdatamanager;
using Incendios0_1.tools;
using System.Configuration;
using Incendios0_1.Camera;
using AsyncCamera.Camera.media;
using Incendios0_1.Camera.media;

namespace AsyncCamera.Camera.Pelco
{
    class IPCameraSource: MediaSource
    {
        private static int retries = 5;
    
        private int errors;
        public int Errors
        {
            get
            {
                errorLock.EnterReadLock();
                try
                {
                    return errors;
                }
                finally
                {
                    errorLock.ExitReadLock();
                }
            }
            set
            {
                if (errorLock.TryEnterWriteLock(timeOut))
                {
                    try
                    {
                        errors=value;
                    }
                    finally
                    {
                        errorLock.ExitWriteLock();
                    }
                }
            }
        }
        private ReaderWriterLockSlim errorLock;

        private Dictionary<Double,FrameGrabber> grabbers;
        public Dictionary<Double, FrameGrabber> Grabbers
        {
            get { return this.grabbers; }
        }

        private double counter;

        public int bufferSize { get; set; }

        public IPCameraSource(AbstractCamera camera)
            : base()
        {
            currentState = MediaState.Stop;
            grabbers = new Dictionary<double, FrameGrabber>();
            this.AttachedCamera = camera;
            counter = 0;
            bufferSize = 5;
            errorLock = new ReaderWriterLockSlim();
        }

        private void TestConnection()
        {
            frame = new Frame();
            frame.Id = 0;
            try
            {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(AttachedCamera.cameraData.Url);
                try
                {
                    myRequest.ReadWriteTimeout = Int32.Parse(ConfigurationManager.AppSettings["WaitForCamera"]);
                    myRequest.Timeout = Int32.Parse(ConfigurationManager.AppSettings["WaitForCamera"]);
                }
                catch
                {
                    myRequest.Timeout = 3000;
                    myRequest.ReadWriteTimeout = 3000;
                }
                myRequest.Method = "GET";
                HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse;
                Bitmap bmp = new Bitmap(response.GetResponseStream());
                response.Close();
                frame.Error = MediaError.OK;
                Emgu.CV.Image<Bgr, Byte> img = new Emgu.CV.Image<Bgr, Byte>(bmp);
                frame.Image = img;
                Frame = frame;
            }
            catch (Exception ex)
            {
                frame.Error = MediaError.IPHostUnreachable;
                frame.Message = ex.Message;
                Frame = frame;
                throw new MediaException(ex.Message);
            }
        }

        public override void Start()
        {
            base.Start();
        }

        protected override void Tick(object sender, EventArgs e)
        {
            /*if (grabbers.Count >= retries || grabbers.Count >= bufferSize)
            {
                IEnumerator<FrameGrabber> en = grabbers.Values.Reverse<FrameGrabber>().GetEnumerator();
                int errors = 0;
                while (en.Current != null && en.Current.error != null)
                {
                    ++errors;
                }
                if (errors >= retries)
                {
                    this.Stop();
                    grabbers.Clear();
                }
            }*/
            if (grabbers.Count < bufferSize)
            {
                if (counter < double.MaxValue)
                    ++counter;
                else
                    counter = 0;
                grabbers.Add(counter, new FrameGrabber(this, counter));
            }
            if (errors >= retries)
            {
                this.Stop();
                grabbers.Clear();
            }
        }
    }
}
